<!DOCTYPE html>
<!--
Copyright (c) 2014 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file.
-->

<link rel="import" href="/tracing/base/math/range.html">
<link rel="import" href="/tracing/ui/side_panel/side_panel.html">
<link rel="import" href="/tracing/ui/side_panel/side_panel_registry.html">

<dom-module id='tr-ui-side-panel-container'>
  <template>
    <style>
    :host {
      align-items: stretch;
      display: flex;
      background-color: white;
    }

    :host([expanded]) > #side_panel_drag_handle,
    :host([expanded]) > active-panel-container {
      flex: 1 1 auto;
      border-left: 1px solid black;
      display: flex;
    }

    :host(:not([expanded])) > #side_panel_drag_handle,
    :host(:not([expanded])) > active-panel-container {
      display: none;
    }

    active-panel-container {
      display: flex;
    }

    tab-strip {
      flex: 0 0 auto;
      flex-direction: column;
      -webkit-user-select: none;
      background-color: rgb(236, 236, 236);
      border-left: 1px solid black;
      cursor: default;
      display: flex;
      min-width: 18px; /* workaround for flexbox and writing-mode mixing bug */
      padding: 10px 0 10px 0;
      font-size: 12px;
    }

    tab-strip > tab-strip-label {
      flex-shrink: 0;
      -webkit-writing-mode: vertical-rl;
      white-space: nowrap;
      display: inline;
      margin-right: 1px;
      min-height: 20px;
      padding: 15px 3px 15px 1px;
    }

    tab-strip >
        tab-strip-label:not([enabled]) {
      color: rgb(128, 128, 128);
    }

    tab-strip > tab-strip-label[selected] {
      background-color: white;
      border: 1px solid rgb(163, 163, 163);
      border-left: none;
      padding: 14px 2px 14px 1px;
    }

    #active_panel_container {
      overflow: auto;
    }
    </style>

    <tr-ui-b-drag-handle id="side_panel_drag_handle"></tr-ui-b-drag-handle>
    <active-panel-container id='active_panel_container'>
    </active-panel-container>
    <tab-strip id='tab_strip'></tab-strip>
  </template>
</dom-module>
<script>
'use strict';
Polymer({
  is: 'tr-ui-side-panel-container',

  ready() {
    this.activePanelContainer_ = this.$.active_panel_container;
    this.tabStrip_ = this.$.tab_strip;

    this.dragHandle_ = this.$.side_panel_drag_handle;
    this.dragHandle_.horizontal = false;
    this.dragHandle_.target = this.activePanelContainer_;
    this.rangeOfInterest_ = new tr.b.math.Range();
    this.brushingStateController_ = undefined;
    this.onSelectionChanged_ = this.onSelectionChanged_.bind(this);
    this.onModelChanged_ = this.onModelChanged_.bind(this);
  },

  get brushingStateController() {
    return this.brushingStateController_;
  },

  set brushingStateController(brushingStateController) {
    if (this.brushingStateController) {
      this.brushingStateController_.removeEventListener(
          'change', this.onSelectionChanged_);
      this.brushingStateController_.removeEventListener(
          'model-changed', this.onModelChanged_);
    }
    this.brushingStateController_ = brushingStateController;
    if (this.brushingStateController) {
      this.brushingStateController_.addEventListener(
          'change', this.onSelectionChanged_);
      this.brushingStateController_.addEventListener(
          'model-changed', this.onModelChanged_);
      if (this.model) {
        this.onModelChanged_();
      }
    }
  },

  onSelectionChanged_() {
    if (this.activePanel) {
      this.activePanel.selection = this.selection;
    }
  },

  get model() {
    return this.brushingStateController_.model;
  },

  onModelChanged_() {
    this.activePanelType_ = undefined;
    this.updateContents_();
  },

  get expanded() {
    this.hasAttribute('expanded');
  },

  get activePanel() {
    return this.activePanelContainer_.children[0];
  },

  get activePanelType() {
    return this.activePanelType_;
  },

  set activePanelType(panelType) {
    if (this.model === undefined) {
      throw new Error('Cannot activate panel without a model');
    }

    let panel = undefined;
    if (panelType) {
      panel = document.createElement(panelType);
    }

    if (panel !== undefined && !panel.supportsModel(this.model)) {
      throw new Error('Cannot activate panel: does not support this model');
    }

    if (this.activePanelType) {
      Polymer.dom(this.getLabelElementForPanelType_(
          this.activePanelType)).removeAttribute('selected');
    }

    if (this.activePanelType) {
      this.getLabelElementForPanelType_(
          this.activePanelType).removeAttribute('selected');
    }

    if (this.activePanel) {
      this.activePanelContainer_.removeChild(this.activePanel);
    }

    if (panelType === undefined) {
      Polymer.dom(this).removeAttribute('expanded');
      this.activePanelType_ = undefined;
      return;
    }

    Polymer.dom(this.getLabelElementForPanelType_(panelType)).
        setAttribute('selected', true);
    Polymer.dom(this).setAttribute('expanded', true);

    Polymer.dom(this.activePanelContainer_).appendChild(panel);
    panel.rangeOfInterest = this.rangeOfInterest_;
    panel.selection = this.selection_;
    panel.model = this.model;

    this.activePanelType_ = panelType;
  },

  getPanelTypeForConstructor_(constructor) {
    for (let i = 0; i < this.tabStrip_.children.length; i++) {
      if (this.tabStrip_.children[i].panelType.constructor === constructor) {
        return this.tabStrip_.children[i].panelType;
      }
    }
  },

  getLabelElementForPanelType_(panelType) {
    for (let i = 0; i < this.tabStrip_.children.length; i++) {
      if (this.tabStrip_.children[i].panelType === panelType) {
        return this.tabStrip_.children[i];
      }
    }
    return undefined;
  },

  updateContents_() {
    const previouslyActivePanelType = this.activePanelType;

    Polymer.dom(this.tabStrip_).textContent = '';
    const supportedPanelTypes = [];
    const panelTypeInfos =
      tr.ui.side_panel.SidePanelRegistry.getAllRegisteredTypeInfos();
    const unsupportedLabelEls = [];

    for (const panelTypeInfo of panelTypeInfos) {
      const labelEl = document.createElement('tab-strip-label');
      const panel = panelTypeInfo.constructor();
      const panelType = panel.tagName;

      Polymer.dom(labelEl).textContent = panel.textLabel;
      labelEl.panelType = panelType;

      const supported = panel.supportsModel(this.model);
      if (this.model && supported.supported) {
        supportedPanelTypes.push(panelType);
        Polymer.dom(labelEl).setAttribute('enabled', true);
        labelEl.addEventListener('click', function(panelType) {
          this.activePanelType =
              this.activePanelType === panelType ? undefined : panelType;
        }.bind(this, panelType));
        Polymer.dom(this.tabStrip_).appendChild(labelEl);
      } else {
        if (this.activePanel) {
          this.activePanelContainer_.removeChild(this.activePanel);
        }
        this.removeAttribute('expanded');
        unsupportedLabelEls.push(labelEl);
      }
    }

    // Labels do not shrink, so when the user drags the analysis-view up, the
    // bottom labels are obscured first.
    // Append all unsupported panel labels after all supported panel labels so
    // that unsupported panel labels are obscured first.
    for (const labelEl of unsupportedLabelEls) {
      Polymer.dom(this.tabStrip_).appendChild(labelEl);
    }

    // Restore the active panel, or collapse
    if (previouslyActivePanelType &&
        supportedPanelTypes.includes(previouslyActivePanelType)) {
      this.activePanelType = previouslyActivePanelType;
      Polymer.dom(this).setAttribute('expanded', true);
    } else {
      if (this.activePanel) {
        Polymer.dom(this.activePanelContainer_).removeChild(this.activePanel);
      }
      Polymer.dom(this).removeAttribute('expanded');
    }
  },

  get rangeOfInterest() {
    return this.rangeOfInterest_;
  },

  set rangeOfInterest(range) {
    if (range === undefined) {
      throw new Error('Must not be undefined');
    }
    this.rangeOfInterest_ = range;
    if (this.activePanel) {
      this.activePanel.rangeOfInterest = range;
    }
  }
});
</script>
